package com.zhang.zxx.boot.common.exception;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;
import java.util.function.Function;

/**
 * MessageThrowable:可抛出消息 3层轻量堆栈
 *
 * @author zhangxiaoxiang
 * @date 2021年11月27日
 */
@Slf4j
@NoArgsConstructor
public class MessageThrowable extends RuntimeException {

    @Getter
    private Object debugObject;

    @Getter
    private StackTraceElement traceElement;

    public MessageThrowable setDebugObject(Object debugObject) {
        this.debugObject = debugObject;
        return this;
    }

    public MessageThrowable(String message) {
        super(message);
        try {
            this.traceElement = Thread.currentThread().getStackTrace()[3];
        } catch (Exception e) {
            log.warn("获取MessageThrowable堆栈失败", e);
        }
    }

    public MessageThrowable(String message, Throwable cause) {
        super(message, cause);
    }


    public static void assertThrow(boolean isTrue, String message, String... formatStr) {

        if (isTrue) {
            String replace = message.replace("{}", "%s");
            String format = String.format(replace, (Object[]) formatStr);
            log.info(message, (Object[]) formatStr);
            throw new MessageThrowable(format);
        }
    }

    public static void assertThrow(Function<MessageThrowable, Boolean> isTrueFunction, String message, String... formatStr) {

        String replace = message.replace("{}", "%s");
        String format = String.format(replace, (Object[]) formatStr);
        MessageThrowable throwable = new MessageThrowable(format);

        Boolean bool = Optional.ofNullable(isTrueFunction.apply(throwable)).orElseGet(() -> {
            log.warn("isTrueFunction is null,default false.");
            return false;
        });

        if (bool) {
            log.info(message, (Object[]) formatStr);
            throw throwable;
        }
    }

}
